package com.code2roc.xhood.asm;

import com.code2roc.xhood.model.ObsureEnum;
import com.code2roc.xhood.util.CommonUtil;
import com.code2roc.xhood.util.ObscureUtil;
import org.apache.commons.lang3.StringUtils;
import org.objectweb.asm.*;

import java.util.*;

public class ClassDefineUseVisitor extends ClassVisitor {
    private LinkedHashMap<String, String> modifyMap;
    private HashMap<String, String> sourceMap;

    public ClassDefineUseVisitor(ClassVisitor cv, LinkedHashMap<String, String> modifyMap, HashMap<String, String> sourceMap) {
        super(Opcodes.ASM9, cv);
        this.modifyMap = modifyMap;
        this.sourceMap = sourceMap;
    }

    @Override
    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
        List<String> convertList = new ArrayList<>();
        if (interfaces != null) {
            for (String item : interfaces) {
                for (String key : modifyMap.keySet()) {
                    item = CommonUtil.replace(item, key, modifyMap.get(key));
                }
                convertList.add(item);
            }
            interfaces = new String[convertList.size()];
            interfaces = convertList.toArray(interfaces);
        }
        if (superName != null) {
            for (String key : modifyMap.keySet()) {
                superName = CommonUtil.replace(superName, key, modifyMap.get(key));
            }
        }
        if (signature != null) {
            for (String key : modifyMap.keySet()) {
                signature = CommonUtil.replace(signature, key, modifyMap.get(key));
            }
        }
        super.visit(version, access, name, signature, superName, interfaces);
    }

    @Override
    public void visitSource(String source, String debug) {
        if (source != null) {
            for (String key : sourceMap.keySet()) {
                source = CommonUtil.replace(source, key, sourceMap.get(key));
            }
        }
        super.visitSource(source, debug);
    }

    @Override
    public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
        if (descriptor != null) {
            for (String key : modifyMap.keySet()) {
                descriptor = CommonUtil.replace(descriptor, key, modifyMap.get(key));
            }
        }
        if (signature != null) {
            for (String key : modifyMap.keySet()) {
                signature = CommonUtil.replace(signature, key, modifyMap.get(key));
            }
        }
        return super.visitField(access, name, descriptor, signature, value);
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
        if (descriptor != null) {
            for (String key : modifyMap.keySet()) {
                descriptor = CommonUtil.replace(descriptor, key, modifyMap.get(key));
            }
        }
        if (signature != null) {
            for (String key : modifyMap.keySet()) {
                signature = CommonUtil.replace(signature, key, modifyMap.get(key));
            }
        }

        if (exceptions != null) {
            for (int i = 0; i < exceptions.length; i++) {
                for (String key : modifyMap.keySet()) {
                    exceptions[i] = CommonUtil.replace(exceptions[i], key, modifyMap.get(key));
                }
            }
        }
        MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
        return new EmptyAdapter(mv);
    }

    @Override
    public void visitInnerClass(String name, String outerName, String innerName, int access) {
        if (name != null) {
            for (String key : modifyMap.keySet()) {
                name = CommonUtil.replace(name, key, modifyMap.get(key));
            }
        }
        if (outerName != null) {
            for (String key : modifyMap.keySet()) {
                outerName = CommonUtil.replace(outerName, key, modifyMap.get(key));
            }
        }
        if (innerName != null) {
            for (String key : modifyMap.keySet()) {
                innerName = CommonUtil.replace(innerName, key, modifyMap.get(key));
            }
        }
        super.visitInnerClass(name, outerName, innerName, access);
    }

    @Override
    public void visitOuterClass(String owner, String name, String descriptor) {
        if (owner != null) {
            for (String key : modifyMap.keySet()) {
                owner = CommonUtil.replace(owner, key, modifyMap.get(key));
            }
        }
        if (name != null) {
            for (String key : modifyMap.keySet()) {
                name = CommonUtil.replace(name, key, modifyMap.get(key));
            }
        }
        if (descriptor != null) {
            for (String key : modifyMap.keySet()) {
                descriptor = CommonUtil.replace(descriptor, key, modifyMap.get(key));
            }
        }
        super.visitOuterClass(owner, name, descriptor);
    }

    @Override
    public RecordComponentVisitor visitRecordComponent(String name, String descriptor, String signature) {
        if (name != null) {
            for (String key : modifyMap.keySet()) {
                name = CommonUtil.replace(name, key, modifyMap.get(key));
            }
        }
        if (descriptor != null) {
            for (String key : modifyMap.keySet()) {
                descriptor = CommonUtil.replace(descriptor, key, modifyMap.get(key));
            }
        }
        if (signature != null) {
            for (String key : modifyMap.keySet()) {
                signature = CommonUtil.replace(signature, key, modifyMap.get(key));
            }
        }
        return super.visitRecordComponent(name, descriptor, signature);
    }

    @Override
    public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
        if (descriptor != null) {
            for (String key : modifyMap.keySet()) {
                descriptor = CommonUtil.replace(descriptor, key, modifyMap.get(key));
            }
        }
        AnnotationVisitor annotationVisitor = super.visitAnnotation(descriptor, visible);
        return new ClassAnnotationAdapter(annotationVisitor, modifyMap);
    }

    @Override
    public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) {
        if (descriptor != null) {
            for (String key : modifyMap.keySet()) {
                descriptor = CommonUtil.replace(descriptor, key, modifyMap.get(key));
            }
        }
        AnnotationVisitor annotationVisitor = super.visitTypeAnnotation(typeRef, typePath, descriptor, visible);
        return new ClassAnnotationAdapter(annotationVisitor, modifyMap);
    }

}
